package memo

import "sync"

type Memo3 struct {
	f     Func
	mu    sync.Mutex
	cache map[string]result
}

func (memo *Memo3) Get(key string) (value interface{}, err error) {
	memo.mu.Lock()
	res, ok := memo.cache[key]
	memo.mu.Unlock()

	if !ok {
		res.value, res.err = memo.f(key)

		// 在两个临界区域之前，可能会有多个 goroutine 来计算 f(key) 并且更新 map
		memo.mu.Lock()
		memo.cache[key] = res
		memo.mu.Unlock()
	}
	return res.value, res.err
}
